<?php


namespace App\Http\Library;


class Excel
{
    /*不需要重复解析文件*/
    private static $filePath = [];
    private static $excel;
    /*PHPExcel*/
    private static $xlsObj;
    /*Excel第一行是否加粗*/
    public static $isBold = true;
    /*定义title key=>name OR [[key=>name],[key2=>name2]]*/
    public static $title = [];
    /*对指定单元格添加背景颜色*/
    public static $backColor = 0xA5E0FF;
    /*设置列宽*/
    public static $rowWidth = [
        'A:A' => 20,
        'B:B' => 16,
    ];
    /*在指定路径生产文件*/
    public static $fileTmp = null;
    /*下载文件*/
    public static $download = false;
    /*是否冻结第一行*/
    public static $freeze = true;

    /**
     * 生成临时文件
     *
     * @return string
     */
    private static function getTmpDir($path = '') :string
    {
        $tmp = ini_get('upload_tmp_dir');
        if ($tmp !== false && file_exists($tmp)) {
            return realpath($tmp) . $path;
        }
        return realpath(sys_get_temp_dir()) . $path;
    }


    /**
     * 获取一个文件名
     *
     * @param string $sha1File
     * @param string $suffix
     *
     * @return string
     */
    private static function getFileName(string $sha1File, $suffix = '')
    {
        /*文件后缀*/
        $suffix = empty($suffix) ? '' : ".{$suffix}";
        return sprintf('%s_%s%s', date('YmdHis'), $sha1File, $suffix);
    }


    /**
     * 待样式的导出excel
     *
     * @param array  $data
     * @param string $fileName
     */
    public static function send($data = [], string $fileName = 'fileName')
    {
        $initFileName = $fileName;
        $config = [];
        /*是否需要保存文件*/
        if (!empty(self::$fileTmp)) {
            $config['path'] = self::$fileTmp;
        }
        /*是否下载*/
        if (self::$download == true) {
            $config['path'] = self::getTmpDir('/');
            $initFileName = self::getFileName(uniqid(), 'xlsx');
        }
        self::$xlsObj = new \Vtiful\Kernel\Excel($config);
        /*此处会自动创建一个工作表*/
        $obj = self::$xlsObj->fileName($initFileName);
        $obj->header(self::$title)->data($data);
        /*是否冻结第一行*/
        if (self::$freeze) {
            $obj->freezePanes(1, 0);
        }
        /*获取文件句柄*/
        $fileHandle = $obj->getHandle();
        $format = new \Vtiful\Kernel\Format($fileHandle);
        /*设置字体*/
        $fontStyle = $format->font('Microsoft YaHei Light')->toResource();
        /*设置列宽*/
        if (!empty(self::$rowWidth)) {
            foreach (self::$rowWidth as $key => $val) {
                $obj->setColumn($key, $val, $fontStyle);
            }
        }
        /*Excel第一行是否加粗*/
        if (self::$isBold) {
            /*重新获取文件句柄*/
            $fileHandle = $obj->getHandle();
            $format = new \Vtiful\Kernel\Format($fileHandle);
            $boldStyle = $format->bold()->toResource();
            $obj->setRow('A1', 16, $boldStyle);
        }
        /*对指定单元格添加背景颜色*/
        if (!empty(self::$backColor)) {
            $format->background(self::$backColor)->toResource();
        }
        $filePath = $obj->output();
        if (self::$download == true) {
            // Set Header
            header("Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            header(sprintf('Content-Disposition: attachment;filename=%s', urlencode($fileName)));
            header('Content-Length: ' . filesize($filePath));
            header('Content-Transfer-Encoding: binary');
            header('Cache-Control: must-revalidate');
            header('Cache-Control: max-age=0');
            header('Pragma: public');
            ob_clean();
            flush();
            if (copy($filePath, 'php://output') === false) {
                throw new \Exception('文件下载异常');
            }
            /*删除临时文件*/
            @unlink($filePath);
        }
        return $filePath;
    }


    /**
     * 读取指定路径Excel内容
     *
     * @param string $filePath
     * @param bool   $isAll
     *
     * @return array
     */
    public static function read(string $filePath, bool $isAll = true, bool $isFormat = true)
    {
        if (!in_array($filePath, self::$filePath)) {
            self::$filePath[] = $filePath;
            $config = ['path' => dirname($filePath)];
            self::$excel = new \Vtiful\Kernel\Excel($config);
            /*读取文件*/
            self::$excel->openFile(basename($filePath))->openSheet();
        }
        /*判断是否需要全量返回*/
        if ($isAll == true) {
            $data = [];
            $currentRow = 1;
            $currentKey = [];
            while (($row = self::$excel->nextRow()) !== null) {
                /*判断是否需要格式化*/
                if ($isFormat == true) {
                    if ($currentRow == 1) {
                        $currentKey = $row;
                    } else {
                        /*如果整行都是空的,则跳过处理*/
                        if (self::isEmpty($row)) {
                            continue;
                        }
                        foreach ($row as $k => $v) {
                            !isset($currentKey[$k]) OR $data[$currentRow][$currentKey[$k]] = $v;
                        }
                    }
                    $currentRow++;
                } else {
                    $data[] = $row;
                }
            }
            return $data;
        }
        /*返回单条*/
        return self::$excel->nextRow();
    }


    /**
     * 如果整行都是空的,则跳过处理
     *
     * @param $data
     *
     * @return bool
     */
    private static function isEmpty($data)
    {
        if (empty($data)) {
            return true;
        }
        foreach ($data as $v) {
            if (!empty($v)) {
                return false;
            }
        }
        return true;
    }


    /**
     * 导出
     *
     * @param $filePath     存放路径
     * @param $fileName     文件名称
     * @param $header       表头
     * @param $data         数据
     */
    public static function write($filePath, $fileName, $header, $data)
    {
        $config = ['path' => $filePath];
        $excel = new \Vtiful\Kernel\Excel($config);

        $filePath = $excel->constMemory($fileName)->header($header);

        $data[] = $data;

        $filePath->data($data);

        $filePath->output();
    }
}





/**
 * Excel.php
 *
 * 说明:
 *
 * 修改历史
 * ----------------------------------------
 * 2021/6/7 18:51:00   操作:创建
 **/
